package demoMod.nanaki.stances;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.evacipated.cardcrawl.modthespire.lib.SpirePatch;
import com.evacipated.cardcrawl.modthespire.lib.SpireReturn;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.actions.unique.LoseEnergyAction;
import com.megacrit.cardcrawl.actions.watcher.ChangeStanceAction;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.DamageInfo;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.localization.StanceStrings;
import com.megacrit.cardcrawl.powers.AbstractPower;
import com.megacrit.cardcrawl.relics.AbstractRelic;
import com.megacrit.cardcrawl.stances.AbstractStance;
import com.megacrit.cardcrawl.vfx.BorderFlashEffect;
import demoMod.anm2player.AnimatedActor;
import demoMod.nanaki.NanakiMod;
import demoMod.nanaki.interfaces.EndOfTurnHook;
import demoMod.nanaki.interfaces.ExitStropheHook;
import demoMod.nanaki.patches.GameActionManagerPatch;
import demoMod.nanaki.utils.GetWaitAction;
import demoMod.nanaki.vfx.StropheCircleEffect;
import demoMod.nanaki.vfx.StropheParticleEffect;

import java.util.stream.Collectors;

public class Strophe3 extends AbstractStrophe {
    public static final String STANCE_ID = "Nanaki:Strophe3";

    private static final StanceStrings stanceString = CardCrawlGame.languagePack.getStanceString(STANCE_ID);

    private static long sfxId = -1L;
    private static long introId = -1L;
    private StropheCircleEffect circleEffect;

    public Strophe3() {
        this.ID = STANCE_ID;
        this.name = stanceString.NAME;
        updateDescription();
    }

    public void updateDescription() {
        this.description = stanceString.DESCRIPTION[0];
    }

    public void updateAnimation() {
        if (!Settings.DISABLE_EFFECTS) {
            this.particleTimer2 -= Gdx.graphics.getDeltaTime();

            if (this.particleTimer2 < 0.0F) {
                this.particleTimer2 = 0.1F;
                AbstractDungeon.effectsQueue.add(new StropheParticleEffect(AbstractDungeon.player.hb.cX - AbstractDungeon.player.hb.width / 2.0F, AbstractDungeon.player.hb.cY - AbstractDungeon.player.hb.height / 2.0F - 48.0F * Settings.scale, StropheParticleEffect.ParticleType.FOVER));
            }
        }
    }

    public float atDamageGive(float damage, DamageInfo.DamageType type) {
        if (type == DamageInfo.DamageType.NORMAL)
            return damage * 1.2F;
        return damage;
    }

    private AbstractGameAction playIntroSfxAction;
    private AbstractGameAction playLoopSfxAction;
    private boolean exitSfxPlayed = false;

    public void onEnterStance() {
        if (sfxId != -1L) stopIdleSfx();
        NanakiMod.addToBot(GetWaitAction.doAndWait(() -> CardCrawlGame.sound.play("STROPHE_3_ENTER"), 2.474F));
        playIntroSfxAction = GetWaitAction.doAndWait(() -> introId = CardCrawlGame.sound.play("STROPHE_3_INTRO"), 9.897F);
        NanakiMod.addToBot(playIntroSfxAction);
        playLoopSfxAction = new AbstractGameAction() {
            @Override
            public void update() {
                sfxId = CardCrawlGame.sound.playAndLoop("STROPHE_3_LOOP");
                isDone = true;
            }
        };
        NanakiMod.addToBot(playLoopSfxAction);
        AbstractDungeon.effectsQueue.add(new BorderFlashEffect(Color.GOLD, true));
        circleEffect = new StropheCircleEffect(getStropheLevel());
        AbstractDungeon.effectsQueue.add(circleEffect);
    }

    @Override
    public void onEndOfTurn() {
        AbstractDungeon.actionManager.addToBottom(new ChangeStanceAction("Neutral"));
        for (AbstractCard card : AbstractDungeon.player.drawPile.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        for (AbstractCard card : AbstractDungeon.player.hand.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        for (AbstractCard card : AbstractDungeon.player.discardPile.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        GameActionManagerPatch.StropheExitedThisTurn = 0;
    }

    public void onExitStance() {
        GameActionManagerPatch.StropheExitedThisTurn++;
        for (AbstractCard card : AbstractDungeon.player.drawPile.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractCard card : AbstractDungeon.player.hand.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractCard card : AbstractDungeon.player.discardPile.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractPower power : AbstractDungeon.player.powers.stream().filter(p -> p instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) power).onExitStrophe();
        }
        for (AbstractRelic relic : AbstractDungeon.player.relics.stream().filter(p -> p instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) relic).onExitStrophe();
        }
        AbstractDungeon.actionManager.addToBottom(new LoseEnergyAction(1));
        stopIdleSfx();
        for (AnimatedActor actor : vfxList) {
            actor.setCurAnimation("exit");
        }
        circleEffect.dismiss();
    }

    public void stopIdleSfx() {
        if (playLoopSfxAction != null) {
            if (sfxId != -1L) {
                CardCrawlGame.sound.stop("STROPHE_3_LOOP", sfxId);
                sfxId = -1L;
            }
            NanakiMod.cancelAction(playLoopSfxAction);
        }
        if (playIntroSfxAction != null) {
            if (introId != -1L) {
                CardCrawlGame.sound.stop("STROPHE_3_INTRO", introId);
                introId = -1L;
            }
            NanakiMod.cancelAction(playIntroSfxAction);
        }
        if (!exitSfxPlayed) {
            CardCrawlGame.sound.play("STROPHE_3_EXIT");
            exitSfxPlayed = true;
        }
    }

    @Override
    public int getStropheLevel() {
        return 3;
    }

    @Override
    public AbstractStrophe getNextStrophe() {
        return null;
    }

    @SpirePatch(clz = AbstractStance.class, method = "getStanceFromName")
    static public class getStanceFromNamePatch {
        static public SpireReturn<AbstractStance> Prefix(String name) {
            if (name.equals(Strophe3.STANCE_ID))
                return SpireReturn.Return(new Strophe3());
            if (name.equals(Strophe2.STANCE_ID))
                return SpireReturn.Return(new Strophe2());
            if (name.equals(Strophe1.STANCE_ID))
                return SpireReturn.Return(new Strophe1());
            return SpireReturn.Continue();
        }
    }
}
